﻿using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Resources;
using EnvDTE;
using EnvDTE80;

namespace VsTortoiseSVN
{
    public static class DTE2ExtensionMethods
    {
        /// <summary>
        /// Gets whether a document is active and exists on the file system.
        /// </summary>
        public static bool HasDocument(this DTE2 dte)
        {
            if (dte.ActiveDocument == null)
                return false;

            return !string.IsNullOrEmpty(dte.ActiveDocument.FullName);
        }

        /// <summary>
        /// Gets whether a solution file is active and exists on the file system.
        /// </summary>
        public static bool HasSolution(this DTE2 dte)
        {
            if (dte.Solution == null)
                return false;

            return dte.Solution.IsOpen && !string.IsNullOrEmpty(dte.Solution.FullName);
        }

        /// <summary>
        /// Gets whether a project file is active that exists on the file system.
        /// </summary>
        public static bool HasProject(this DTE2 dte)
        {
            if (!dte.HasSolution())
                return false;

            return dte.ActiveSolutionProjects != null &&
                dte.Solution.Projects != null && dte.Solution.Projects.Count > 0;
        }

        public static Project ActiveProject(this DTE2 dte)
        {
            Array projects = dte.ActiveSolutionProjects as Array;
            if(projects.Length > 0)
                return projects.GetValue(0) as Project;

            return null;
        }

        /// <summary>
        /// Saves all currently opened documents.
        /// </summary>
        public static bool SaveDocuments(this DTE2 dte)
        {
            foreach (EnvDTE.Document document in dte.Documents)
            {
                if (!document.Save())
                    return false;
            }

            return true;
        }
    }


    public static class SolutionExtensionMethods
    {
        public static string LongFullName(this EnvDTE.Solution solution)
        {
            return PathHelper.GetLongPathName(solution.FullName);
        }

        public static void GetDirectoryNames(this EnvDTE.Solution solution, ICollection<string> dest)
        {
            // Add Solution directory to list
            dest.Add(Path.GetDirectoryName(solution.LongFullName()));

            // Add all Project directories to list
            for (int n = 1; n <= solution.Projects.Count; ++n)
            {
                Project project = solution.Projects.Item(n);
                if (!string.IsNullOrEmpty(project.FullName))
                    project.GetDirectoryNames(dest);
            }
        }
    }

    public static class ProjectExtensionMethods
    {
        public static string LongFullName(this EnvDTE.Project project)
        {
            string path = PathHelper.GetLongPathName(project.FullName);
            return path;
        }

        private static void GetDirectoryNamesRecursive(this EnvDTE.Project project, Dictionary<string, int> folders, ProjectItem projectItem)
        {
            // Check if this is a physically existing file
            // as we are only interested in this.
            if (string.Compare(projectItem.Kind, Constants.vsProjectItemKindPhysicalFile, true) == 0)
            {
                string filename = projectItem.get_FileNames(0);
                string directory = Path.GetDirectoryName(filename);

                if (!folders.ContainsKey(directory))
                    folders.Add(directory, 1);
            }

            // If this item has sub-items, process them too
            foreach (ProjectItem item in projectItem.ProjectItems)
            {
                GetDirectoryNamesRecursive(project, folders, item);
            }
        }

        public static void GetDirectoryNames(this EnvDTE.Project project, ICollection<string> dest)
        {
            // the dictionary is used as fast approach to
            // look up if a directory has been added to the list already
            Dictionary<string, int> folders = new Dictionary<string, int>(128, StringComparer.OrdinalIgnoreCase);

            // Check each project item
            foreach (ProjectItem projectItem in project.ProjectItems)
                GetDirectoryNamesRecursive(project, folders, projectItem);

            // Add folders to destination
            foreach (string folder in folders.Keys)
                dest.Add(PathHelper.GetLongPathName(folder));
        }
    }

    public static class DocumentExtensionMethods
    {
        public static string LongFullName(this EnvDTE.Document document)
        {
            return PathHelper.GetLongPathName(document.FullName);
        }

        public static bool Save(this EnvDTE.Document document)
        {
            if (document.Saved)
                return true; // not modified

            string filename = document.LongFullName();
            bool success = document.Save(filename) == vsSaveStatus.vsSaveSucceeded;
            return success;
        }
    }

    public static class TextSelectionExtensionMethods
    {
        public static void GotoLineCentered(this EnvDTE.TextSelection selection, int line)
        {
            int offset = selection.TextPane.Height / 2;

            if (line > selection.TextPane.StartPoint.Line + selection.TextPane.Height)
            {
                selection.GotoLine(line + offset, false);
                selection.LineUp(false, offset);
            }
            else if (line < selection.TextPane.StartPoint.Line)
            {
                selection.GotoLine(line - offset, false);
                selection.LineDown(false, offset);
            }
            else
            {
                selection.GotoLine(line, false);
            }
        }
    }
}
